/**
 * gulp 的入口文件
 * 由于运行在 Nodejs 环境中，因此可使用 commomJS 规范
 * 通过导出函数成员的方式定义构建任务
 */
// 这种写法会报错，因为 gulp 约定任务都是异步任务，需要调用回调函数标记任务结束
// exports.foo = () => {
//   console.log('foo')
// }


exports.foo = done => {
  console.log('foo')
  done() // 标记任务结束
}

// 默认任务：名称是 default
exports.default = done => {
  console.log('default task')
  done()
}

// 使用具体的模块注册任务
const gulp = require('gulp')
gulp.task('bar', done => {
  console.log('bar task')
  done()
})


/**
 * 组合任务
 */
// 这种未被导出的成员函数理解为私有任务，此时不能通过 gulp 直接运行
const task1 = done => {
  setTimeout(() => {
    console.log('task1')
    done()
  }, 1000);
}
const task2 = done => {
  setTimeout(() => {
    console.log('task2')
    done()
  }, 1000);
}
const task3 = done => {
  setTimeout(() => {
    console.log('task3')
    done()
  }, 1000);
}
// 通过 两个 api 将上面的任务组合起来
const { series, parallel } = require('gulp')

// 串行任务，按顺序依次执行
exports.seriesTask = series(task1, task2, task3)

// 并行任务，任务同时启动，同步执行
exports.parallelTask = parallel(task1, task2, task3)


/**
 * 异步任务
 */
/***** 异步任务1：回调函数的方式 *****/
exports.callback = done => {
  console.log('callback')
  done()
}
// 异步任务1：错误优先的回调函数，可给回调函数的第一个参数传递错误对象，阻止后续任务执行
exports.callback_error = done => {
  console.log('callback_error')
  done(new Error('throw callback_error'))
}

/***** 异步任务2：promise *****/
exports.promise = () => {
  console.log('promise')
  // 返回一个 promise 的 resolve，无需传递参数，因为 gulp 会忽略
  return Promise.resolve()
}
// 异步任务2：promise 失败
exports.promise_error = () => {
  console.log('promise_error')
  return Promise.reject(new Error('throw promise_error'))
}

/***** 异步任务3： async/await *****/
// 定义一个 promise 任务包装 setTimeout
const timeout = time => {
  return new Promise(resolve => {
    setTimeout(resolve, time);
  })
}
// 将任务函数定义为异步函数，在函数中 await 一个异步任务（promise）
exports.asyncTask = async () => {
  await timeout(1000)
  console.log('async settimeout')
}

/***** stream *****/
/**
 * 以文件读取为例
 * 任务函数中需返回一个 stream 对象，
 * 任务结束的时机是 readStream 在 end 的时候，
 * 读取文件流读取完成之后会触发 end 事件，gulp 便会知道任务已完成
 */
const fs = require('fs')
exports.stream = () => {
  // 创建读取文件的文件流
  const readStream = fs.createReadStream('package.json')
  const writeStream = fs.createWriteStream('temp.txt')
  // 将 readStream 通过 pipe 的方式导入 writeStream 中，起到文件复制的作用
  readStream.pipe(writeStream)
  return readStream
}

// 模拟 gulp 执行流程
exports.stream2 = done => {
  // 创建读取文件的文件流
  const readStream = fs.createReadStream('package.json')
  const writeStream = fs.createWriteStream('temp.txt')
  readStream.pipe(writeStream)
  // gulp 接收到stream之后注册了一个 end 事件，在 end 事件中结束了任务
  readStream.on('end', () => {
    done()
  })
}